#include <Kharlia/Client/Common.h>
#include <Kharlia/Client/TileRender.h>
#include <Kharlia/Client/Engine.h>
#include <Kharlia/Core/App.h>

namespace Kharlia { namespace Client {
    TileRender::TileRender(Engine::Ptr engine, uint32 width, uint32 height,
                           uint32 tileWidth, uint32 tileHeight, const std::string& tileSet):
            mEngine(engine),
            mTileXWidth(tileWidth),
            mTileYHeight(tileHeight),
            mLevelWidth(width),
            mLevelHeight(height),
            mTileset(tileSet) {
        mValid = true;
        CEGUI::Renderer* ren = engine->GetRenderer();
        try {
            if (mLevelWidth > 0 && mLevelHeight > 0) {
                mTileVector.resize(mLevelWidth * mLevelHeight);
                mTileTexture = dynamic_cast<CEGUI::Texture*>(
                    ren->createTexture(tileSet.c_str(),"tilesets")
                );
            }
            else {
                mValid = false;
                throw Exception("Error: level width or height should be nonzero");
            }
        }
        catch(CEGUI::Exception& e)
        {
            mValid = false;
            std::cerr << e.getMessage().c_str() << std::endl;
        }
        // Get the tile texture -Inverness
        if (mTileset.empty()) {
            mTileTexture = engine->GetErrorTexture();
        }
        else {
            try {
                glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // temporary?
                mTileTexture = ren->createTexture(mTileset.c_str(), "tilesets");
            }
            catch(CEGUI::Exception& e) {
                std::cerr << e.getMessage().c_str() << std::endl;
                mTileTexture = engine->GetErrorTexture();
            }
        }
        if (mTileXWidth > 0 && mTileYHeight > 0) {

        }
        else {
            mValid = false;
            throw Exception("Tile X Width or Tile Y Width were less than one.");
        }
    }

    void TileRender::UpdateTile(uint32 ix, uint32 iy,uint32 newx, uint32 newy)
    {
        if (ix*iy < mTileVector.size())
        {
            mTileVector[(iy*mLevelWidth)+ix].X = newx;
            mTileVector[(iy*mLevelWidth)+ix].Y = newy;
        }
    }

    void TileRender::Draw()
    {
        CEGUI::OpenGLTexture* tiletex = static_cast<CEGUI::OpenGLTexture*>(mTileTexture);
        glBindTexture(GL_TEXTURE_2D, tiletex->getOGLTexid());
        for (uint32 i = 0 ; i < mLevelWidth * mLevelHeight ; i ++)
        {
            glBegin(GL_QUADS);

            // TOP LEFT
            glTexCoord2f(
                float((mTileVector[i].X*mTileXWidth)*mTileTexture->getXScale()),
                float((mTileVector[i].Y*mTileYHeight)*mTileTexture->getYScale())
                );    
            glVertex2d(
                (i%(mLevelWidth))*mTileXWidth,
                (ceilf((i/mLevelWidth)-.5f)*mTileYHeight)
                );

            // TOP RIGHT
            glTexCoord2f(
                float(((mTileVector[i].X+1)*mTileXWidth)*mTileTexture->getXScale()),
                float(((mTileVector[i].Y)*mTileYHeight)*mTileTexture->getYScale())
                );
            glVertex2d(
                ((i%(mLevelWidth))*mTileXWidth)+mTileXWidth,
                (ceilf((i/mLevelWidth)-.5f)*mTileYHeight)
                );

            // BOTTOM RIGHT
            glTexCoord2f(
                float(((mTileVector[i].X+1)*mTileXWidth)*mTileTexture->getXScale()),
                float(((mTileVector[i].Y+1)*mTileYHeight)*mTileTexture->getYScale())
                );
            glVertex2d(
                ((i%(mLevelWidth))*mTileXWidth)+mTileXWidth,
                (ceilf((i/mLevelWidth)-.5f)*mTileYHeight)+mTileYHeight
                );
            // BOTTOM LEFT
            glTexCoord2f(
                float(((mTileVector[i].X)*mTileXWidth)*mTileTexture->getXScale()),
                float(((mTileVector[i].Y+1)*mTileYHeight)*mTileTexture->getYScale())
                );
            glVertex2d(
                ((i%(mLevelWidth))*mTileXWidth),
                (ceilf((i/mLevelWidth)-.5f)*mTileYHeight)+mTileYHeight
                );
        }
    }

} }
